{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "092b84e6",
   "metadata": {},
   "source": [
    "## 内置工具\n",
    "\n",
    "https://python.langchain.ac.cn/docs/integrations/tools/\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "e30bf1a7",
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install -qU duckduckgo-search langchain-community ddgs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "69305731",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'2025年7月22日 — 1976年4月，史蒂夫·賈伯斯、史蒂夫·沃茲尼亞克和羅納德·韋恩創立了蘋果公司，目的是為了研發和銷售沃茲尼亞克Apple I個人電腦，但韋恩12天後就放棄了自己的股份。 2025年7月13日 — 1976年，沃茲尼克與史蒂夫·賈伯斯合夥創立蘋果電腦公司，並在1970年代末研發出第一代和第二代蘋果電腦。 二代電腦一經發售即風靡全美，成為1970-80年代之交銷量最佳的個人電 ... 2024年10月8日 — 乔布斯 的离世引发了全球科技从业者的哀悼。他不仅是苹果公司的创始人，还是一位卓越的创新者，其对产品设计、创业和企业管理的见解深刻影响了科技界。 美国 司 法部称 苹 果 公 司 是非法垄断企业，并基于有着上百年历史 的 《谢尔曼法》对这家 公 司 提起诉讼。 《华尔街日报》请反垄断律师分析了 司 法部 的 法律论据，以及 苹 果 公 司 可能如何反击。 Spotify于2019年3月向欧洲监管机构提出了针对 苹 果 的 反托拉斯投诉。 “ 苹 果 公 司 已向App Store引入新增规则，目 的 是限制选择并扼杀 创 新，以牺牲用户体验为代价。 ” 公 司 创 始 人 兼首席执行官Daniel Ek当时表示。'"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_community.tools import DuckDuckGoSearchRun\n",
    "\n",
    "search = DuckDuckGoSearchRun()\n",
    "\n",
    "search.invoke(\"苹果公司的创始人 ?\")\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "47ca243a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'snippet': '2025年7月22日 — 1976年4月，史蒂夫·賈伯斯、史蒂夫·沃茲尼亞克和羅納德·韋恩創立了蘋果公司，目的是為了研發和銷售沃茲尼亞克Apple I個人電腦，但韋恩12天後就放棄了自己的股份。',\n",
       "  'title': '蘋果公司- 維基百科，自由的百科全書',\n",
       "  'link': 'https://zh.wikipedia.org/zh-hk/蘋果公司'},\n",
       " {'snippet': '2025年7月13日 — 1976年，沃茲尼克與史蒂夫·賈伯斯合夥創立蘋果電腦公司，並在1970年代末研發出第一代和第二代蘋果電腦。 二代電腦一經發售即風靡全美，成為1970-80年代之交銷量最佳的個人電 ...',\n",
       "  'title': '史蒂夫·沃茲尼克',\n",
       "  'link': 'https://zh.wikipedia.org/zh-hk/史蒂夫·沃兹尼亚克'},\n",
       " {'snippet': '在他生活 的 年代裡，喬布斯被認為是電腦業界與娛樂業界 的 標誌性人物，同時 人 們也把他視作 mac 、 iPod 、 iPhone 、 iPad 等知名數碼產品 的 締造者。 他亦曾七次登上《時代雜誌》封面，被認為是当时全球最為成功 的 商人之一。',\n",
       "  'title': '史蒂夫·乔布斯 - 维基百科，自由的百科全书',\n",
       "  'link': 'https://zh.wikipedia.org/wiki/史蒂夫·乔布斯'},\n",
       " {'snippet': '2024年10月8日 — 乔布斯 的离世引发了全球科技从业者的哀悼。他不仅是苹果公司的创始人，还是一位卓越的创新者，其对产品设计、创业和企业管理的见解深刻影响了科技界。',\n",
       "  'title': '离世13周年，重温乔布斯的100条思考',\n",
       "  'link': 'https://finance.sina.com.cn/stock/stockzmt/2024-10-08/doc-incrvssy7197443.shtml'}]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 溯源\n",
    "\n",
    "from langchain_community.tools import DuckDuckGoSearchResults\n",
    "\n",
    "search = DuckDuckGoSearchResults(output_format=\"list\")\n",
    "\n",
    "search.invoke(\"苹果公司的创始人 ?\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f95e09f8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "my_search_tool\n",
      "通过搜索引擎查询\n",
      "{'query': {'title': 'Query', 'type': 'string'}}\n",
      "\n",
      "问题: 苹果公司的创始人是谁？\n",
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m我应该使用搜索工具来查找苹果公司的创始人是谁。\n",
      "Action: my_search_tool\n",
      "Action Input: \"苹果公司的创始人是谁\"\u001b[0m\u001b[36;1m\u001b[1;3m['2025年7月13日 — 1976年，沃茲尼克與史蒂夫·賈伯斯合夥創立蘋果電腦公司，並在1970年代末研發出第一代和第二代蘋果電腦。 二代電腦一經發售即風靡全美，成為1970-80年代之交銷量最佳的個人電 ...', '1 day ago · 네이버 동영상 검색 은 네이버의 동영상 검색 서비스이다. 2005년 12월 네이버 동영상 검색 오픈 베타 서비스가 시작되었다.', '1 日前 — 1976年4月1日，乔布斯、沃兹和罗纳德·杰拉尔德·韦恩（Ronald Gerald Wayne）在乔布斯父母的车库里创立合伙企业“ 苹果 电脑 公司 ” 。韦恩是乔布斯在雅达利的同事，在合伙企业期间为 ...', '2025年2月17日 — 十年前 蘋果 前 創始人 喬布斯（Steve Jobs）結束了他傳奇的一生。隨後，庫克（Tim Cook）接過了 蘋果 的大旗，至今也已十年之久。而這十年間，眾人對庫克的評價是褒貶不一的，庫克也 ...']\u001b[0m\u001b[32;1m\u001b[1;3m根据搜索结果，苹果公司的创始人是史蒂夫·乔布斯（Steve Jobs）。\n",
      "Final Answer: 史蒂夫·乔布斯（Steve Jobs）是苹果公司的创始人。\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n",
      "答案: 史蒂夫·乔布斯（Steve Jobs）是苹果公司的创始人。\n",
      "--------------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "from langchain.tools import tool\n",
    "from langchain_community.tools import DuckDuckGoSearchResults\n",
    "from langchain.agents import create_react_agent, AgentExecutor\n",
    "from langchain.prompts import PromptTemplate\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "# 创建搜索工具\n",
    "search_wrapper = DuckDuckGoSearchResults(output_format=\"list\")\n",
    "\n",
    "@tool(\"my_search_tool\")\n",
    "def search(query: str) -> list[str]:\n",
    "    \"\"\"通过搜索引擎查询\"\"\"\n",
    "    result = search_wrapper.invoke(query)\n",
    "    return [res[\"snippet\"] for res in result]\n",
    "\n",
    "print(search.name)\n",
    "print(search.description)\n",
    "print(search.args)\n",
    "\n",
    "\n",
    "def create_react_search_agent():\n",
    "    tools = [search]\n",
    "    llm = ChatOpenAI(temperature=0, model=\"gpt-3.5-turbo\")\n",
    "    \n",
    "    \n",
    "    prompt = PromptTemplate.from_template(\"\"\"\n",
    "        Answer the following questions as best you can. You have access to the following tools:\n",
    "\n",
    "        {tools}\n",
    "\n",
    "        Use the following format:\n",
    "\n",
    "        Question: the input question you must answer\n",
    "        Thought: you should always think about what to do\n",
    "        Action: the action to take, should be one of [{tool_names}]\n",
    "        Action Input: the input to the action\n",
    "        Observation: the result of the action\n",
    "        ... (this Thought/Action/Action Input/Observation can repeat N times)\n",
    "        Thought: I now know the final answer\n",
    "        Final Answer: the final answer to the original input question\n",
    "\n",
    "        Begin!\n",
    "\n",
    "        Question: {input}\n",
    "        Thought:{agent_scratchpad}\"\"\")\n",
    "    \n",
    "    agent = create_react_agent(llm, tools, prompt)\n",
    "    \n",
    "    agent_executor = AgentExecutor(\n",
    "        agent=agent,\n",
    "        tools=tools,\n",
    "        verbose=True,\n",
    "        max_iterations=3,\n",
    "        handle_parsing_errors=True  # 这个很重要！\n",
    "    )\n",
    "    \n",
    "    return agent_executor\n",
    "\n",
    "# 使用修复后的 Agent\n",
    "agent = create_react_search_agent()\n",
    "\n",
    "# 测试\n",
    "questions = [\"苹果公司的创始人是谁？\"]\n",
    "\n",
    "for question in questions:\n",
    "    print(f\"\\n问题: {question}\")\n",
    "    response = agent.invoke({\"input\": question})\n",
    "    print(f\"答案: {response['output']}\")\n",
    "    print(\"-\" * 50)\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "MLOps",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
